package com.happyhome.controller;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.imgscalr.Scalr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import com.happyhome.constants.AppConstant;
import com.happyhome.datamodel.Image;
import com.happyhome.datamodel.News;
import com.happyhome.datamodel.Parameter;
import com.happyhome.services.ImageService;
import com.happyhome.services.NewsService;
import com.happyhome.services.ParameterService;

@Controller
@RequestMapping("/admin/news")
public class NewsController {
	
	private static final Logger log = LoggerFactory.getLogger(NewsController.class);
	
	@Autowired
	private NewsService newsService;
	
	@Autowired
	private ImageService imageService;
	
	@Autowired
	private ServletContext context;
	
	@Autowired
	private ParameterService parameterService;
	
	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public ModelAndView login() {
		return new ModelAndView("/admin/news/list");
	}
	
	@RequestMapping(value = "/new", method = RequestMethod.GET)
	public ModelAndView newRoom() {
		ModelAndView model = new ModelAndView("/admin/news/new");
		return model;
	}
	
	/* form new House submit form */
	@RequestMapping(value = "/newNewsSubmit", method = RequestMethod.POST)
	public @ResponseBody String newRoomSubmit(MultipartHttpServletRequest request, HttpServletResponse response){
		Map<String, String[]> multiParameters = request.getParameterMap();
		Iterator<String> itr =  request.getFileNames();
		 
	    MultipartFile mpf = request.getFile(itr.next());
	    
		News news = setValueForNews(null, multiParameters);
		if(news != null){ // input invalid in setValueForHouse
			String newFilenameBase = UUID.randomUUID().toString();
            String originalFileExtension = mpf.getOriginalFilename().substring(mpf.getOriginalFilename().lastIndexOf("."));
            String newFilename = newFilenameBase + originalFileExtension;
            
            String filename = "/WEB-INF" ;
			String pathname = context.getRealPath(filename);
			
			File dir = new File(pathname + File.separator + "images");
			
			if(!dir.exists()){
				dir.mkdirs();
			}
			
            String contentType = mpf.getContentType();
            
            File newFile = new File(dir.getAbsolutePath() + File.separator + newFilename);
            try {
                mpf.transferTo(newFile);
                
                BufferedImage thumbnail = Scalr.resize(ImageIO.read(newFile), 80);
                String thumbnailFilename = newFilenameBase + "-thumbnail.png";
                File thumbnailFile = new File(dir.getAbsolutePath() + File.separator + thumbnailFilename);
                ImageIO.write(thumbnail, "png", thumbnailFile);
                
                Image image = new Image();
                image.setName(mpf.getOriginalFilename());
                image.setThumbnailFilename(thumbnailFilename);
                image.setNewFilename(newFilename);
                image.setContentType(contentType);
                image.setSize(mpf.getSize());
                image.setThumbnailSize(thumbnailFile.length());
                image.setDateCreated(new Date());
                image.setLastUpdated(new Date());
                image = imageService.merge(image);
                news.setImageThumbnail(image);
                news = newsService.merge(news);
            } catch(IOException e) {
                log.error("Could not upload file " + mpf.getOriginalFilename(), e);
                return "fail";
            }
			return news.getIdNews() + ";" + news.getTitleNews();
		}
		return "fail";
	}
	
	private News setValueForNews(News news, Map<String, String[]> multiParameters){
		if(news == null){
			news = new News();
		}
		
		String[] titleNews = multiParameters.get(AppConstant.TITLE_NEWS);
		if(titleNews != null ){
			news.setTitleNews(titleNews[0]);
			multiParameters.remove(AppConstant.TITLE_NEWS);
		}
		
		String[] content = multiParameters.get(AppConstant.CONTENT);
		if(content != null ){
			news.setContent(content[0]);
			multiParameters.remove(AppConstant.CONTENT);
		}
		
		String[] imageValue = multiParameters.get(AppConstant.IMAGE_THUMBNAIL);
		if(imageValue != null ){
			Image image = imageService.getImageByNewFileName(imageValue[0]);
			news.setImageThumbnail(image);
		}
		
		// set status to true
		news.setStatus(Boolean.valueOf("true"));
		news.setMakeDate(new Date());
		
		return news;
	}
	
	/* edit room */
 	@RequestMapping(value = "/edit/{newsId}", method = RequestMethod.GET)
 	public ModelAndView editRoom(@PathVariable Long newsId){
 		News news = newsService.findNesById(newsId);
		
		ModelAndView model = new ModelAndView("/admin/news/edit");
		
		news.setThumbnailUrl("/" + AppConstant.APP_URL + "/admin/images/picture/"+ news.getImageThumbnail().getId());
		model.addObject("news", news);
		
		return model;
 	}
 	
 	/* delete new */
 	@RequestMapping(value = "/deleteNews/{newsId}", method = RequestMethod.POST)
    public @ResponseBody String deleteNews(@PathVariable Long newsId) {
        News news = newsService.getNewsById(newsId);
        if(news.getImageThumbnail() != null){
        	Long imageThumbnailId = news.getImageThumbnail().getId();
        	String pathname = context.getRealPath(AppConstant.IMAGE_LOCATION);
            File imageFile = new File(pathname + "/" + news.getImageThumbnail().getNewFilename());
            imageFile.delete();
            File thumbnailFile = new File(pathname + "/" + news.getImageThumbnail().getThumbnailFilename());
            thumbnailFile.delete();
            news.setImageThumbnail(null);
            news.setStatus(Boolean.valueOf("false"));
            newsService.merge(news);
            imageService.deleteImageById(imageThumbnailId);
        }else{
        	news.setStatus(Boolean.valueOf("false"));
            newsService.merge(news);
        }
        return "success";
    }
 	
 	@RequestMapping(value = "/editNewSubmit", method = RequestMethod.POST)
 	public @ResponseBody String editNewSubmit(MultipartHttpServletRequest request, HttpServletResponse response){
		Map<String, String[]> multiParameters = request.getParameterMap();
		Iterator<String> itr =  request.getFileNames();
		 
	    MultipartFile mpf = request.getFile(itr.next());
	    News newsTarget = newsService.findNesById(Long.parseLong(multiParameters.get("idNews")[0]));
		News news = setValueForNews(newsTarget, multiParameters);
		if(mpf != null){ // input invalid in setValueForHouse
			// delete old image thumbnail before add another image thumbnail
			Image image = imageService.getImageById(newsTarget.getImageThumbnail().getId());
	        String pathname = context.getRealPath(AppConstant.IMAGE_LOCATION);
	        File imageFile = new File(pathname + "/" + image.getNewFilename());
	        imageFile.delete();
	        File thumbnailFile = new File(pathname + "/" + image.getThumbnailFilename());
	        thumbnailFile.delete();
	        
	        // create new image thumbnail
			String newFilenameBase = UUID.randomUUID().toString();
            String originalFileExtension = mpf.getOriginalFilename().substring(mpf.getOriginalFilename().lastIndexOf("."));
            String newFilename = newFilenameBase + originalFileExtension;
            
			File dir = new File(pathname);
			
			if(!dir.exists()){
				dir.mkdirs();
			}
			
            String contentType = mpf.getContentType();
            
            File newFile = new File(dir.getAbsolutePath() + File.separator + newFilename);
            try {
                mpf.transferTo(newFile);
                
                BufferedImage thumbnail = Scalr.resize(ImageIO.read(newFile), 80);
                String thumbnailFilename = newFilenameBase + "-thumbnail.png";
                File newThumbnailFile = new File(dir.getAbsolutePath() + File.separator + thumbnailFilename);
                ImageIO.write(thumbnail, "png", newThumbnailFile);
                
                Image newImage = new Image();
                newImage.setName(mpf.getOriginalFilename());
                newImage.setThumbnailFilename(thumbnailFilename);
                newImage.setNewFilename(newFilename);
                newImage.setContentType(contentType);
                newImage.setSize(mpf.getSize());
                newImage.setThumbnailSize(newThumbnailFile.length());
                newImage.setDateCreated(new Date());
                newImage.setLastUpdated(new Date());
                newImage = imageService.merge(newImage);
                news.setImageThumbnail(newImage);
                news = newsService.merge(news);
                imageService.deleteImageById(image.getId());
            } catch(IOException e) {
                log.error("Could not upload file " + mpf.getOriginalFilename(), e);
                return "fail";
            }
			return news.getIdNews() + ";" + news.getTitleNews();
		}else{	// no edit thumbnail image
			news = newsService.merge(news);
			return news.getIdNews() + ";" + news.getTitleNews();
		}
	}
	
 	/**
 	 * get All data to return list rooms
 	 * @return
 	 */
 	@RequestMapping(value = "/getDataNews", method = RequestMethod.GET)
    public @ResponseBody List<News> getDataNews() {
    	List<News> listNews = newsService.getAllNews();
	    return listNews;
    }
 	
	@RequestMapping(value = "/picture/{id}", method = RequestMethod.GET)
    public void picture(HttpServletResponse response, @PathVariable Long id) {
        Image image = imageService.getImageById(id);
        String pathname = context.getRealPath(AppConstant.IMAGE_LOCATION);
        File imageFile = new File(pathname + "/"+ image.getNewFilename());
        response.setContentType(image.getContentType());
        response.setContentLength(image.getSize().intValue());
        try {
            InputStream is = new FileInputStream(imageFile);
            IOUtils.copy(is, response.getOutputStream());
        } catch(IOException e) {
            log.error("Could not show picture "+id, e);
        }
    }
    
    @RequestMapping(value = "/thumbnail/{id}", method = RequestMethod.GET)
    public void thumbnail(HttpServletResponse response, @PathVariable Long id) {
        Image image = imageService.getImageById(id);
        String pathname = context.getRealPath(AppConstant.IMAGE_LOCATION);
        File imageFile = new File(pathname + "/" + image.getThumbnailFilename());
        response.setContentType(image.getContentType());
        response.setContentLength(image.getThumbnailSize().intValue());
        if(imageFile.exists()){
	        try {
	            InputStream is = new FileInputStream(imageFile);
	            IOUtils.copy(is, response.getOutputStream());
	        } catch(IOException e) {
	            log.error("Could not show thumbnail "+id, e);
	        }
        }
    }
    
    @RequestMapping(value = "/setDisplayCavas", method = RequestMethod.POST)
    public @ResponseBody String setDisplayCavas(HttpServletRequest request) {
    	List<Long> listLongId = new ArrayList<Long>();
    	Map<String, String[]> multiParameters = request.getParameterMap();
    	String[] listIdNews = multiParameters.get("listIdNews");
    	if(listIdNews != null){
    		String[] listIdNewsValue = listIdNews[0].split(",");
    		try{
    			for(int i = 0; i < listIdNewsValue.length; i++){
    				Long idNews = Long.parseLong(listIdNewsValue[i]);
    				listLongId.add(idNews);
    			}
    			Parameter parameter = parameterService.getParameterByCode(AppConstant.NEWS_CODE);
    			if(listLongId.size() > 0 && parameter.getValue() >= listLongId.size()){
    				newsService.setDisplayCavas(listLongId);
    			}else if(listLongId.size() > 0){
    				return "fail";
    			}
    		}catch(NumberFormatException exception){
    			return "fail";
    		}
    	}
    	return "success";
    }
}
